package org.fly.main.database;

import cn.hutool.db.Db;
import cn.hutool.db.dialect.impl.MysqlDialect;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author whh
 * @Date: 2023/04/14/ 22:04
 * @description
 */

@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = {"org.fly.**.dao"})
public class DataSourceConfig {


    @Autowired
    private DataSourceConfigProperties dataSourceConfigProperty;

    @Bean(name = "druidDataSource",destroyMethod = "close")
    @Primary
    public DruidDataSource druidDataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(dataSourceConfigProperty.getUrl());
        druidDataSource.setDriverClassName(dataSourceConfigProperty.getDriver());
        druidDataSource.setUsername(dataSourceConfigProperty.getUserName());
        druidDataSource.setPassword(dataSourceConfigProperty.getPasswd());
        druidDataSource.setInitialSize(Integer.parseInt(dataSourceConfigProperty.getInitSize()));
        druidDataSource.setMinIdle(Integer.parseInt(dataSourceConfigProperty.getMinIdle()));
        druidDataSource.setMaxActive(Integer.parseInt(dataSourceConfigProperty.getMaxActive()));
        druidDataSource.setMaxWait(dataSourceConfigProperty.getMaxWaitTime());
        druidDataSource.setTimeBetweenEvictionRunsMillis(dataSourceConfigProperty.getEvictionRunTime());
        druidDataSource.setMinEvictableIdleTimeMillis(dataSourceConfigProperty.getMinEvictionIdleTime());
        druidDataSource.setTestWhileIdle(dataSourceConfigProperty.isTestWhileIdle());
        druidDataSource.setTestOnBorrow(dataSourceConfigProperty.isTestOnBorrow());
        druidDataSource.setTestOnReturn(dataSourceConfigProperty.isTestOnReturn());
        druidDataSource.setValidationQuery(dataSourceConfigProperty.getValidationQuery());
        druidDataSource.init();

        return druidDataSource;
    }




    @Bean("dBUtil")
    public Db dBUtil(DataSource dataSource){
        return new Db(dataSource,new MysqlDialect());
    }

    @Bean
    public ServletRegistrationBean<StatViewServlet> servletRegistrationBean() {
        ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>();
        StatViewServlet servlet = new StatViewServlet();
        registrationBean.setServlet(servlet);
        registrationBean.setName("druidView");
        registrationBean.setLoadOnStartup(2);
        List<String> urlMapping = new ArrayList<>();
        urlMapping.add("/druid/*");
        registrationBean.setUrlMappings(urlMapping);
        return registrationBean;
    }



    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactory=new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml"));
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] mapperResources = resolver.getResources("classpath:mapper/**/*.xml"); // 扫描所有子目录的 XML
        sqlSessionFactory.setMapperLocations(mapperResources);
        return sqlSessionFactory.getObject();
    }

    //编程式事务配置
    @Bean
    @Primary
    public DataSourceTransactionManager transactionManager(DruidDataSource druidDataSource) {
        return new DataSourceTransactionManager(druidDataSource);
    }


    @Bean("customTrx")
    @Primary
    public TransactionTemplate customTrx(DataSourceTransactionManager transactionManager) {
        DefaultTransactionDefinition customTrxDefinition = new DefaultTransactionDefinition();
        customTrxDefinition.setPropagationBehaviorName("PROPAGATION_REQUIRED");
        customTrxDefinition.setIsolationLevelName("ISOLATION_READ_COMMITTED");
        customTrxDefinition.setTimeout(600);
        return new TransactionTemplate(transactionManager, customTrxDefinition);
    }

}
